package net.paoding.rose.web.impl.mapping;

import java.util.Arrays;

import net.paoding.rose.web.annotation.ReqMethod;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class AbstractMapping<T> implements Mapping<T> {

	protected Log logger = LogFactory.getLog(getClass());
	protected String path;
	protected ReqMethod[] methods;
	protected String requestMethods = "*"; // 由methods转变而来
	protected T target;

	public AbstractMapping(String path, ReqMethod[] methods, T target) {
		this.path = normalized(path);
		this.target = target;
		this.methods = methods;
		initMethods();
	}

	@Override
	public String getPath() {
		return path;
	}

	@Override
	public T getMappingTarget() {
		return target;
	}

	public boolean isRequestMethodSupported(String requestMethod) {
		if (!requestMethods.equals("*")) {
			requestMethod = requestMethod.toUpperCase();
			if (requestMethods.indexOf(requestMethod) == -1) {
				return false;
			}
		}
		return true;
	}
	
	public boolean isMethodReplicated(AbstractMapping<T> obj) {
		String[] methods = new String[] { "GET", "POST", "DELETE", "OPTIONS",
				"PUT", "HEAD" };
		for (String method : methods) {
			if (this.isRequestMethodSupported(method)
					&& obj.isRequestMethodSupported(method)) {
				return true;
			}
		}
		return false;
	}

	protected String normalized(String path) {
		if (path.length() > 0 && path.charAt(0) != '/') {
			path = '/' + path;
		}
		if (path.equals("/")) {
			path = "";
		}
		while (path.length() > 1 && path.endsWith("/")) {
			path = path.substring(0, path.length() - 1);
		}
		return path;
	}

	protected void initMethods() {
		if (ArrayUtils.contains(methods, ReqMethod.ALL)) {
			requestMethods = "*";
		} else if (methods.length > 0) {
			requestMethods = "";
			for (int i = 0; i < methods.length; i++) {
				if (i == 0) {
					requestMethods = methods[i].toString();
				} else {
					requestMethods += "," + methods[i].toString();
				}
			}
		}
	}
	
	public ReqMethod[] getMethods() {
		return Arrays.copyOf(methods, methods.length);
	}
	
	@Override
	public String toString() {
		return path + "->" + target;
	}

}
